package com.grm.sys.service.impl;

import com.grm.common.exception.BusinessException;
import com.grm.common.utils.TreeUtils;
import com.grm.sys.mapper.SysPermMapper;
import com.grm.sys.mapper.SysRolePermMapper;
import com.grm.sys.model.SysPerm;
import com.grm.sys.request.perm.SysPermAddParam;
import com.grm.sys.request.perm.SysPermUpdateParam;
import com.grm.sys.response.SysPermResponse;
import com.grm.sys.service.SysPermService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class SysPermServiceImpl implements SysPermService {
    @Autowired
    private SysPermMapper sysPermMapper;
    @Autowired
    private SysRolePermMapper sysRolePermMapper;

    @Override
    public List<SysPermResponse> queryAllTree() {
        List<SysPerm> sysPermList = sysPermMapper.queryAllList();
        return sysPermToSysPermResponse(sysPermList);
    }

    @Override
    public List<SysPermResponse> queryMenuTree() {
        List<SysPerm> sysPermList = sysPermMapper.queryListByTypes(Arrays.asList("1", "2"));
        return sysPermToSysPermResponse(sysPermList);
    }

    private List<SysPermResponse> sysPermToSysPermResponse(List<SysPerm> sysPermList) {
        if (ObjectUtils.isNotEmpty(sysPermList)) {
            List<SysPermResponse> sysPermResponseList = new ArrayList<>();
            for (SysPerm sysPerm : sysPermList) {
                SysPermResponse sysPermResponse = new SysPermResponse();
                sysPermResponse.setId(sysPerm.getId());
                sysPermResponse.setParentId(sysPerm.getParentId());
                sysPermResponse.setType(sysPerm.getType());
                sysPermResponse.setName(sysPerm.getName());
                sysPermResponse.setPerm(sysPerm.getPerm());
                sysPermResponse.setSort(sysPerm.getSort());
                sysPermResponse.setIcon(sysPerm.getIcon());
                sysPermResponseList.add(sysPermResponse);
            }
            return TreeUtils.getTree(sysPermResponseList);
        }
        return new ArrayList<>();
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void add(SysPermAddParam sysPermAddParam) {
        SysPerm dbSysPerm = sysPermMapper.queryByName(sysPermAddParam.getName());
        if (dbSysPerm != null) {
            throw new BusinessException("权限已存在，请重新设置权限！");
        }
        SysPerm sysPerm = sysPermAddParamToSysPerm(sysPermAddParam);
        sysPermMapper.insert(sysPerm);
    }

    private SysPerm sysPermAddParamToSysPerm(SysPermAddParam sysPermAddParam) {
        SysPerm sysPerm = new SysPerm();
        sysPerm.setParentId(sysPermAddParam.getParentId());
        sysPerm.setName(sysPermAddParam.getName());
        sysPerm.setType(sysPermAddParam.getType());
        sysPerm.setPerm(sysPermAddParam.getPerm());
        sysPerm.setSort(sysPermAddParam.getSort());
        sysPerm.setIcon(sysPermAddParam.getIcon());
        return sysPerm;
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void update(SysPermUpdateParam sysPermUpdateParam) {
        SysPerm dbSysPerm = sysPermMapper.queryById(sysPermUpdateParam.getId());
        if (dbSysPerm == null) {
            throw new BusinessException("权限不存在！");
        }

        SysPerm dbSysPerm2 = sysPermMapper.queryByParentIdAndName(sysPermUpdateParam.getParentId(), sysPermUpdateParam.getName());
        if (dbSysPerm2 != null && !dbSysPerm2.getId().equals(sysPermUpdateParam.getId())) {
            throw new BusinessException("同层级不能有相同的权限名称！");
        }
        SysPerm sysPerm = sysPermUpdateParamToSysPerm(sysPermUpdateParam);

        sysPermMapper.update(sysPerm);
    }

    private SysPerm sysPermUpdateParamToSysPerm(SysPermUpdateParam sysPermUpdateParam) {
        SysPerm sysPerm = new SysPerm();
        sysPerm.setId(sysPermUpdateParam.getId());
        sysPerm.setParentId(sysPermUpdateParam.getParentId());
        sysPerm.setName(sysPermUpdateParam.getName());
        sysPerm.setType(sysPermUpdateParam.getType());
        sysPerm.setPerm(sysPermUpdateParam.getPerm());
        sysPerm.setSort(sysPermUpdateParam.getSort());
        sysPerm.setIcon(sysPermUpdateParam.getIcon());
        return sysPerm;
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    @Override
    public void delete(Long id) {
        // 判断有没有子权限
        List<SysPerm> sysPermList = sysPermMapper.queryChildPerms(id);
        if (ObjectUtils.isNotEmpty(sysPermList)) {
            throw new BusinessException("该权限下有子权限，请先删除子权限！");
        }
        // 先删除角色权限关系
        sysRolePermMapper.deleteByPermIds(Collections.singletonList(id));
        // 再删除权限
        sysPermMapper.deleteById(id);
    }

    @Override
    public List<SysPermResponse> queryUserMenuTree(Long userId) {
        List<SysPerm> sysPermList;
        if (isAdmin(userId)) {
            sysPermList = sysPermMapper.queryListByTypes(Arrays.asList("1", "2"));
        } else {
            sysPermList = sysPermMapper.querySysPermsByUserIdAndTypes(userId, Arrays.asList("1", "2"));
        }
        return sysPermToSysPermResponse(sysPermList);
    }

    @Override
    public List<Map<String, String>> queryUserRouters(Long userId) {
        List<Map<String, String>> routers = new ArrayList<>();
        List<SysPerm> sysPermList;
        if (isAdmin(userId)) {
            sysPermList = sysPermMapper.queryListByTypes(List.of("2"));
        } else {
            sysPermList = sysPermMapper.querySysPermsByUserIdAndTypes(userId, List.of("2"));
        }
        if (ObjectUtils.isNotEmpty(sysPermList)) {
            for (SysPerm sysPerm : sysPermList) {
                Map<String, String> routerMap = new HashMap<>();
                routerMap.put("title", sysPerm.getName());
                routerMap.put("path", sysPerm.getPerm());
                routers.add(routerMap);
            }
        }
        return routers;
    }

    @Override
    public List<String> queryButtonPermList(Long userId) {
        List<String> buttonPermList = new ArrayList<>();
        List<SysPerm> sysPermList;
        if (isAdmin(userId)) {
            sysPermList = sysPermMapper.queryListByTypes(List.of("3"));
        } else {
            sysPermList = sysPermMapper.querySysPermsByUserIdAndTypes(userId, List.of("3"));
        }
        if (ObjectUtils.isNotEmpty(sysPermList)) {
            for (SysPerm sysPerm : sysPermList) {
                buttonPermList.add(sysPerm.getPerm());
            }
        }
        return buttonPermList;
    }

    private boolean isAdmin(Long userId) {
        return userId.equals(1L);
    }

    @Override
    public List<Long> queryPermIdsByRoleId(Long roleId) {
        return sysRolePermMapper.queryPermIdsByRoleId(roleId);
    }
}
